﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/10/15 11:40:00
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace CommonLibrary
{
    /// <summary>
    /// 扫码枪串口配置
    /// </summary>
    public class ScanComParam : ComParameter
    {
        /// <summary>
        /// 触发地址与结果
        /// </summary>
        [Description("触发地址与结果")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<ScanPLCEntity> PLCEntities = new List<ScanPLCEntity>();
        /// <summary>
        /// 扫码命令
        /// </summary>
        [Description("扫码命令")]
        [JsonProperty(PropertyName = "command")]
        public string Command { get; set; } = "LON\r\n";
        /// <summary>
        /// 用于显示
        /// </summary>
        [JsonIgnore]
        public string CommandText
        {
            get
            {
                return string.IsNullOrWhiteSpace(this.Command) ? string.Empty : this.Command.Replace("\r", "\\r").Replace("\n", "\\n");
            }
        }
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 扫码枪TCP配置
    /// </summary>
    public class ScanTcpParam : TcpParameter
    {
        /// <summary>
        /// 触发地址与结果
        /// </summary>
        [Description("触发地址与结果")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<ScanPLCEntity> PLCEntities = new List<ScanPLCEntity>();
        /// <summary>
        /// 扫码命令
        /// </summary>
        [Description("扫码命令")]
        [JsonProperty(PropertyName = "command")]
        public string Command { get; set; } = "LON\r\n";
        /// <summary>
        /// 用于显示
        /// </summary>
        [JsonIgnore]
        public string CommandText
        {
            get
            {
                return string.IsNullOrWhiteSpace(this.Command) ? string.Empty : this.Command.Replace("\r", "\\r").Replace("\n", "\\n");
            }
        }
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 自定义处理代理
    /// </summary>
    /// <param name="scanHelper"></param>
    /// <param name="barcode"></param>
    /// <param name="checkResult"></param>
    /// <param name="scanTime"></param>
    /// <returns></returns>
    public delegate (short mesResult, bool plcOptFinished) CustomScanHelperJobDelegate(ScanHelper scanHelper, string barcode, EBarcodeCheckResult checkResult, string scanTime);
    /// <summary>
    /// 数据通知代理
    /// </summary>
    /// <param name="barcode"></param>
    /// <param name="checkResult"></param>
    /// <param name="scanTime"></param>
    public delegate void NotifyScanHelperJobDelegate(string barcode, EBarcodeCheckResult checkResult, string scanTime);
    /// <summary>
    /// 扫码枪帮助类
    /// </summary>
    public class ScanHelper : BaseHelper
    {
        /// <summary>
        /// TCP配置文件
        /// </summary>
        static string autoTcpScanConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "ScanTCPConfig.json");
        /// <summary>
        /// 串口配置文件（自动扫码枪）
        /// </summary>
        static string autoComScanConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "ScanComConfig.json");
        /// <summary>
        /// 手动扫码枪配置文件
        /// </summary>
        static string manualComScanConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "ManualScanComConfig.json");
        #region tcp auto
        /// <summary>
        /// 获取TCP扫码枪配置，返回List对象
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static List<ScanTcpParam> GetAutoScanTCPConfig()
        {
            return CommonHelper.GetJsonListFromFile<ScanTcpParam>(autoTcpScanConfigPath);
        }
        /// <summary>
        /// 保存TCP配置内容
        /// </summary>
        /// <param name="list"></param>
        public static void SaveAutoScanTCPConfig(List<ScanTcpParam> list)
        {
            CommonHelper.SaveToJsonFile(list, autoTcpScanConfigPath);
        }
        #endregion
        #region auto com
        /// <summary>
        /// 获取串口配置内容（自动扫码枪）
        /// </summary>
        /// <returns></returns>
        public static List<ScanComParam> GetAutoScanComConfig()
        {
            return CommonHelper.GetJsonListFromFile<ScanComParam>(autoComScanConfigPath);
        }
        /// <summary>
        /// 保存串口配置内容（自动扫码枪）
        /// </summary>
        /// <param name="list"></param>
        public static void SaveAutoScanComConfig(List<ScanComParam> list)
        {
            CommonHelper.SaveToJsonFile(list, autoComScanConfigPath);
        }
        #endregion
        #region manual com
        /// <summary>
        /// 获取手动扫码枪配置内容
        /// </summary>
        /// <returns></returns>
        public static List<ScanComParam> GetManualScanComConfig()
        {
            return CommonHelper.GetJsonListFromFile<ScanComParam>(manualComScanConfigPath);
        }
        /// <summary>
        /// 保存手动扫码枪配置内容
        /// </summary>
        /// <param name="list"></param>
        public static void SaveManualScanComConfig(List<ScanComParam> list)
        {
            CommonHelper.SaveToJsonFile(list, manualComScanConfigPath);
        }
        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        public ScanHelper()
        {
            this.ManualSerialHandler = () =>
            {
                ManualHandler();
            };
        }
        #region 每个Helper特定的参数
        /// <summary>
        /// 扫码次数
        /// </summary>
        public int RepeatTimes => BusinessConfig.Instance().ScanRepeatTimes;
        /// <summary>
        /// 错误barcode
        /// </summary>
        public readonly string ERROR_BARCODE = "ERROR";
        /// <summary>
        /// 自定义处理，可以处理一些MES交互，保存计数等等
        /// </summary>
        public CustomScanHelperJobDelegate CustomScanHelperJob { get; set; } = null;
        /// <summary>
        /// 数据通知处理
        /// </summary>
        public NotifyScanHelperJobDelegate NotifyScanHelperJob { get; set; } = null;
        /// <summary>
        /// 是否需要检查长度
        /// </summary>
        public bool IsNeedCheckBarcodeLength => BusinessConfig.Instance().IsCheckBarcodeLength;
        /// <summary>
        /// 验证的标准长度值
        /// </summary>
        public int BarcodeLegth => BusinessConfig.Instance().BarcodeLength;
        /// <summary>
        /// 是否需要检查前缀
        /// </summary>
        public bool IsNeedCheckBarcodePrev => BusinessConfig.Instance().IsCheckBarcodePrev;
        /// <summary>
        /// 验证的标准前缀值
        /// </summary>
        public string StartValue => BusinessConfig.Instance().BarcodePrev;
        /// <summary>
        /// 开始命令
        /// </summary>
        public string StartCommand { get; set; } = "LON\r\n";
        /// <summary>
        /// 结束命令
        /// </summary>
        public string EndCommand { get; set; } = string.Empty;//"LOFF\r\n";
        #endregion
        /// <summary>
        /// PLC业务
        /// </summary>
        /// <param name="barcode"></param>
        /// <param name="checkResult"></param>
        /// <param name="plcEntity"></param>
        private void BusinessHandler(ref string barcode, ref EBarcodeCheckResult checkResult, ScanPLCEntity plcEntity)
        {
            if (plcEntity != null)
            {
                var param = new ScanExcuteEntity()
                {
                    PlcEntity = plcEntity,
                    Barcode = barcode,
                    ScanTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };
                #region Barcode
                param = CommonHelper.GetJson(PluginManager.Instance.Excute(this.Name, "SCAN_BARCODE", CommonHelper.GetJsonString(param, Formatting.None)), param);
                checkResult = CommonHelper.GetEnumByRealValue(param.ScanResult, EBarcodeCheckResult.NG);
                string scanTime = param.ScanTime;
                #endregion
                #region  MES
                param.MESResult = short.Parse(PluginManager.Instance.Excute(this.Name, "SCAN_MES", CommonHelper.GetJsonString(param, Formatting.None)));
                #endregion
                #region  PLC
                PluginManager.Instance.Excute(this.Name, "SCAN_PLC", CommonHelper.GetJsonString(param, Formatting.None));
                #endregion                
                if (this.NotifyScanHelperJob != null)
                {
                    this.NotifyScanHelperJob(barcode, checkResult, scanTime);
                }
            }
        }
        /// <summary>
        /// 手动串口处理
        /// </summary>
        /// <returns></returns>
        public void ManualHandler()
        {
            this.RealShowMessage($"【{this.Name}】触发手动扫码");
            Stopwatch stopwatch = Stopwatch.StartNew();
            if (this.TriggerHandlers != null && this.TriggerHandlers.Count > 0)
            {
                object otherData = this.TriggerHandlers[0].OtherAddress;
                string barcode = ERROR_BARCODE;
                EBarcodeCheckResult checkResult = EBarcodeCheckResult.NG;
                if (this.IsConnected)
                {
                    try
                    {
                        CommonHelper.ApplicationEvents(30);
                        byte[] buffer = this.SerialRead();
                        if (buffer != null)
                        {
                            barcode = Encoding.UTF8.GetString(buffer);
                            barcode = string.IsNullOrWhiteSpace(barcode) ? ERROR_BARCODE : CommonHelper.RemoveEnterString(barcode);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                    finally
                    {
                        ScanPLCEntity entity = otherData as ScanPLCEntity;
                        BusinessHandler(ref barcode, ref checkResult, entity);
                    }
                }
                stopwatch.Stop();
                this.RealShowMessage($"【{this.Name}】手动扫码，耗时：{stopwatch.ElapsedMilliseconds} 毫秒，扫码值：{barcode}，扫码结果：{checkResult}。");
            }
        }
        /// <summary>
        /// 串口方式获取条码
        /// </summary>
        /// <returns></returns>
        private string GetComBarcode()
        {
            string barcode = "";
            if (this.IsConnected)
            {
                try
                {
                    this.SerialSendString(this.StartCommand);
                    barcode = this.GetSerialReturnUTF8String();
                    if (!string.IsNullOrWhiteSpace(this.EndCommand))
                    {
                        this.SerialSendString(this.EndCommand);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            }
            return barcode;
        }
        /// <summary>
        /// TCP方式获取条码
        /// </summary>
        /// <returns></returns>
        private string GetTcpBarcode()
        {
            string barcode = "";
            if (this.IsConnected)
            {
                try
                {
                    this.TcpSend(Encoding.UTF8.GetBytes(this.StartCommand));
                    barcode = this.TcpReceiveString();
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            }
            return barcode;
        }
        /// <summary>
        /// 获取条码
        /// </summary>
        /// <returns></returns>
        public string GetBarcode()
        {
            string result = this.CommunicationType == ECommunicationType.SERIAL ? GetComBarcode() : GetTcpBarcode();
            LogHelper.Info($"【{this.Name}】获取条码：{result}");
            return result;
        }
        /// <summary>
        /// 业务处理
        /// </summary>
        /// <param name="handlerName"></param>
        /// <param name="handlerType"></param>
        /// <param name="otherAddress"></param>
        /// <param name="otherData"></param>
        public override void RealHandler(string handlerName, EHandlerType handlerType, object otherAddress, object otherData)
        {
            this.RealShowMessage($"【{this.Name}】{handlerName}");
            string barcode = ERROR_BARCODE;
            EBarcodeCheckResult checkResult = EBarcodeCheckResult.NG;
            Stopwatch stopwatch = Stopwatch.StartNew();
            if (this.IsConnected)
            {
                try
                {
                    for (var i = 0; i < this.RepeatTimes; i++)
                    {
                        barcode = GetBarcode();
                        //如果为空或错误条码，重新扫码
                        if (!string.IsNullOrWhiteSpace(barcode) && !ERROR_BARCODE.Equals(barcode))
                        {
                            break;
                        }
                    }
                    barcode = string.IsNullOrWhiteSpace(barcode) ? ERROR_BARCODE : CommonHelper.RemoveEnterString(barcode);
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
                finally
                {
                    ScanPLCEntity entity = otherAddress as ScanPLCEntity;
                    BusinessHandler(ref barcode, ref checkResult, entity);
                }
            }
            stopwatch.Stop();
            this.RealShowMessage($"【{this.Name}】自动扫码，耗时：{stopwatch.ElapsedMilliseconds} 毫秒，扫码值：{barcode}，扫码结果：{checkResult}。", checkResult == EBarcodeCheckResult.OK);
        }
    }
}
